package ru.tennisworld.match.services.match.impl;

import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ru.tennisworld.match.entities.Match;
import ru.tennisworld.match.exceptions.MatchServiceException;
import ru.tennisworld.match.mappers.MatchMapper;
import ru.tennisworld.match.repositories.MatchRepository;
import ru.tennisworld.match.services.ValidationService;
import ru.tennisworld.match.services.match.MatchService;
import ru.tennisworld.match.utils.IntegrationClient;

@Service("matchService")
public class MatchServiceImpl implements MatchService {

    @Autowired
    private IntegrationClient integrationClient;

    @Autowired
    private ValidationService validationService;

    @Autowired
    private MatchRepository matchRepository;

    @Autowired
    private MatchMapper matchMapper;

    private static final Logger LOG = LoggerFactory.getLogger(MatchServiceImpl.class);

    @Override
    public Match getMatchById(Long matchId) {
        LOG.info("operation=MatchServiceImpl.getMatchById, action=start, id={}", matchId);
        Match match = matchRepository.findById(matchId).orElseThrow(
                () -> new MatchServiceException("Матч не найден!")
        );
        LOG.info("operation=MatchServiceImpl.getMatchById, action=end, result={}", match);
        return match;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Match createMatch(Match match) {
        LOG.info("operation=MatchServiceImpl.createMatch, action=start, match={}", match);
        validationService.validateMatch(match);
        matchRepository.save(match);
        LOG.info("operation=MatchServiceImpl.createMatch, action=end, result={}", match);
        return match;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public Match updateMatch(Match src, Match upd) {
        LOG.info("operation=MatchServiceImpl.updateMatch, action=start, src={}, upd={}", src, upd);
        matchMapper.updateMatch(upd, src);
        validationService.validateMatch(src);
        matchRepository.save(src);
        LOG.info("operation=MatchServiceImpl.updateMatch, action=end, result={}", src);
        return src;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUserRatingAfterMatch(Match match) {
        LOG.info("operation=MatchServiceImpl.updateUserRatingAfterMatch, action=start, match={}", match);
        if (BooleanUtils.isTrue(match.getIsFinished())) {
            try {
                integrationClient.updateUserRatingAfterMatch(matchMapper.mapToUserUpdateRequestDto(match));
            } catch (Exception exception) {
                LOG.info("operation=MatchServiceImpl.updateUserRatingAfterMatch, action=error, ex={}", exception.getMessage());
                throw new MatchServiceException("Ошибка обновления рейтинга пользователей после матча", exception);
            }
        }
        LOG.info("operation=MatchServiceImpl.updateUserRatingAfterMatch, action=end");
    }

}
